#if defined(ESP32)
#include <WiFi.h>
#include <HTTPClient.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#endif
#include <WiFiUdp.h>
#include <ArduinoJson.h>
#include <EEPROM.h>
#include <Ticker.h>
char config_flag = 0;     // 判断是否配网
#define MAGIC_NUMBER 0xAA // 判断是否配网
struct config_type
{
  char stassid[32];
  char stapsw[16];
  char cuid[40];
  char ctopic[32];
  uint8_t reboot;
  uint8_t magic;
};
config_type config;
char packetBuffer[255]; // 发送数据包
WiFiUDP Udp;
WiFiClient client_bemfa_WiFiClient;
HTTPClient http_bemfa_HTTPClient;
String topicAP = "";
bool firstWIfiConfig = false;
uint8_t *p = (uint8_t *)(&config);
void loadConfig() {
  uint8_t mac[6];
  WiFi.macAddress(mac);
  #ifdef ESP32
  EEPROM.begin(512);
  #else
  EEPROM.begin(256);
  #endif
  for (int i = 0; i < sizeof(config); i++) {
    *(p + i) = EEPROM.read(i);
  }
  config.reboot = config.reboot + 1;
  if (config.reboot >= 4) {
    restoreFactory();
  }
  if (config.magic != 0xAA) {
    config_flag = 1;
  }
  #ifdef ESP32
  EEPROM.begin(512);
  #else
  EEPROM.begin(256);
  #endif
  for (int i = 0; i < sizeof(config); i++) {
    EEPROM.write(i, *(p + i));
  }
  EEPROM.commit();
  delay(2000);
  #ifdef ESP32
  EEPROM.begin(512);
  #else
  EEPROM.begin(256);
  #endif
  config.reboot = 0;
  for (int i = 0; i < sizeof(config); i++) {
    EEPROM.write(i, *(p + i));
  }
  EEPROM.commit();
}

void restoreFactory() {
  Serial.println("Restore Factory....... ");
  config.magic = 0x00;
  strcpy(config.stassid, "");
  strcpy(config.stapsw, "");
  strcpy(config.cuid, "");
  strcpy(config.ctopic, "");
  config.magic = 0x00;
  saveConfig();
  delayRestart(1);
  while (1) {
    delay(100);
  }
}

void saveConfig() {
  config.reboot = 0;
  #ifdef ESP32
  EEPROM.begin(512);
  #else
  EEPROM.begin(256);
  #endif
  uint8_t *p = (uint8_t *)(&config);
  for (int i = 0; i < sizeof(config); i++) {
    EEPROM.write(i, *(p + i));
  }
  EEPROM.commit();
}

Ticker delayTimer;

void delayRestart(float t) {
  delayTimer.attach(t, []()
                    { ESP.restart(); });
}

void apConfig(String mac) {
  if (config_flag == 1) {
    WiFi.softAP("bemfa_" + mac);
    Udp.begin(8266);
    Serial.println("Started Ap Config...");
  }
  topicAP = mac + "002";
  while (config_flag) { // 如果未配网，开启AP配网，并接收配网信息
    int packetSize = Udp.parsePacket();
    if (packetSize) {
      Serial.print("Received packet of size ");
      Serial.println(packetSize);
      Serial.print("From ");
      IPAddress remoteIp = Udp.remoteIP();
      Serial.print(remoteIp);
      Serial.print(", port ");
      Serial.println(Udp.remotePort());

      int len = Udp.read(packetBuffer, 255);
      if (len > 0) {
        packetBuffer[len] = 0;
      }
      Serial.println("Contents:");
      Serial.println(packetBuffer);
      StaticJsonDocument<200> doc;

      DeserializationError error = deserializeJson(doc, packetBuffer);
      if (error) {
        Serial.print(F("deserializeJson() failed: "));
        Serial.println(error.f_str());
        return;
      }
      int cmdType = doc["cmdType"].as<int>();

      if (cmdType == 1) {
        const char *ssid = doc["ssid"];
        const char *password = doc["password"];
        const char *token = doc["token"];
        strcpy(config.stassid, ssid);
        strcpy(config.stapsw, password);
        strcpy(config.cuid, token);
        // 收到信息，并回复
        String ReplyBuffer = "{\"cmdType\":2,\"productId\":\"" + topicAP + "\",\"deviceName\":\"\",\"protoVersion\":\"3.1\"}";
        Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
        #ifdef ESP32
        Udp.print(ReplyBuffer.c_str());
        #else
        Udp.write(ReplyBuffer.c_str());
        #endif
        Udp.endPacket();
      } else if (cmdType == 3) {
        config_flag = 0;
        firstWIfiConfig = true;
        WiFi.softAPdisconnect(true);
      }
    }
  }
}

void checkFirstConfig() {
  if (firstWIfiConfig) {
    bool httpRequestOk = false;
    while (httpRequestOk == false) {
      if (WiFi.status() == WL_CONNECTED) {
        // 设置目标 URL
        http_bemfa_HTTPClient.begin(client_bemfa_WiFiClient, "http://pro.bemfa.com/vs/web/v1/deviceAddTopic");

        // 创建 JSON 对象
        StaticJsonDocument<200> jsonDoc;
        jsonDoc["uid"] = config.cuid;
        jsonDoc["topic"] = topicAP;
        jsonDoc["type"] = 3;
        jsonDoc["wifiConfig"] = 1; // 必填字段
        jsonDoc["unCreate"] = 1;   // 是否不创建，1不创建,0创建
        // 将 JSON 对象转换为字符串
        String jsonString;
        serializeJson(jsonDoc, jsonString);
        http_bemfa_HTTPClient.addHeader("Content-Type", "application/json; charset=UTF-8");
        // 发送请求
        int httpCode = http_bemfa_HTTPClient.POST(jsonString);
        if (httpCode == 200) {
          httpRequestOk = true;
          Serial.println("POST succeeded with code:");
          Serial.println(httpCode);
          String payload = http_bemfa_HTTPClient.getString();
          Serial.println(payload);

          // json数据解析
          StaticJsonDocument<200> doc;
          DeserializationError error = deserializeJson(doc, payload);
          if (error) {
            Serial.print(F("deserializeJson() failed: "));
            Serial.println(error.c_str());
          }

          int code = doc["code"];
          if (code == 0) {
            int resCode = doc["data"]["code"];
            if (resCode == 40006 || resCode == 0) {
              String docUID = doc["uid"];
              if (firstWIfiConfig)
              {
                config.reboot = 0;
                config.magic = 0xAA;
                saveConfig();
              }
            } else {
              Serial.println(" config ERROR.........");
            }
          } else {
            Serial.println(" config ERROR.........");
          }
        } else if (httpCode != 200) {
          Serial.println("POST failed with code:");
          Serial.println(httpCode);
        } else {
          Serial.println("Unknown error");
        }
        http_bemfa_HTTPClient.end();
      }
      delay(1000); // 每秒检查一次
    }
  }
}
